#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#include "esp_netif_sntp.h"
#include "esp_sntp.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "wifi_main.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_mac.h" // 提供 MACSTR 等 MAC 地址相关宏
#include "main_ui.h"
#include "esp_smartconfig.h"
static const char *TAG = "wifi_main";
EventGroupHandle_t s_wifi_event_group = NULL;
static uint8_t connect_count = 0;
static bool is_scan = false;
static bool is_first_wifi_init = false; //第一次初始化wifi标志
static char ip4_addr[16];
// 事件处理实例和网络接口对象
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
esp_netif_t *sta_netif = NULL;

static void wifi_callback(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { //wifi启动成功
        xEventGroupSetBits(s_wifi_event_group, WIFI_START_BIT);
        /*当调用 esp_wifi_connect() 时，WiFi 驱动会首先检查你是否已经通过 esp_wifi_set_config() 设置了配置。如果没有，它会自动去 NVS 存储区中查找最近一次成功连接的配置并使用它来发起连接。*/
        if (is_scan == false)
            esp_wifi_connect();                                                       // 连接wifi
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { //wifi断开连接

        wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
        ESP_LOGI(TAG, "Station " MACSTR " left, AID=%d, reason:%d",
                 MAC2STR(event->mac), event->aid, event->reason);
        connect_count++;
        //todo 这里应该根据断开原因判断是否需要重新连接wifi
        if (connect_count < EXAMPLE_ESP_MAXIMUM_RETRY) {
            esp_wifi_connect();
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
        ESP_LOGI(TAG, "connect to the AP fail");

    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { //STA成功接入热点并获取IP成功
        ip_event_got_ip_t *info = (ip_event_got_ip_t *)event_data;          //获取IP事件数据
        snprintf(ip4_addr, sizeof(ip4_addr), IPSTR, IP2STR(&info->ip_info.ip));
        ESP_LOGI(TAG, "got ip: %s" ,ip4_addr);
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);

    }
    /***************************SmartConfig事件处理*****************************************/
    else if (event_base == SC_EVENT) {
        switch (event_id) {
            case SC_EVENT_SCAN_DONE:
                // 智能配网扫描完成
                ESP_LOGI(TAG, "smartconfig scan done");
                break;
            case SC_EVENT_FOUND_CHANNEL:
                // 找到目标AP的信道
                ESP_LOGI(TAG, "Found channel");
                break;
            case SC_EVENT_GOT_SSID_PSWD:
                // 获取到SSID和密码
                // 获取到SSID和密码
                ESP_LOGI(TAG, "Got SSID and password");

                // 解析事件数据
                smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
                wifi_config_t wifi_config;
                uint8_t ssid[33] = { 0 };     // SSID缓冲区（32字符+空终止符）
                uint8_t password[65] = { 0 }; // 密码缓冲区（64字符+空终止符）
                uint8_t rvd_data[33] = { 0 }; // 保留数据缓冲区

                // 初始化wifi配置结构
                bzero(&wifi_config, sizeof(wifi_config_t));
                // 复制SSID和密码到wifi配置
                memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
                memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));

                // 设置是否使用BSSID
                wifi_config.sta.bssid_set = evt->bssid_set;
                if (wifi_config.sta.bssid_set == true) {
                    // 复制目标AP的MAC地址
                    ESP_LOGI(TAG, "Set MAC address of target AP: " MACSTR " ", MAC2STR(evt->bssid));
                    memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
                }

                // 复制SSID和密码到本地缓冲区用于日志输出
                memcpy(ssid, evt->ssid, sizeof(evt->ssid));
                memcpy(password, evt->password, sizeof(evt->password));
                ESP_LOGI(TAG, "SSID:%s", ssid);
                ESP_LOGI(TAG, "PASSWORD:%s", password);

                // 如果是ESPTOUCH V2协议，获取保留数据
                if (evt->type == SC_TYPE_ESPTOUCH_V2) {
                    ESP_ERROR_CHECK(esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)));
                    ESP_LOGI(TAG, "RVD_DATA:");
                    // 打印保留数据（十六进制格式）
                    for (int i = 0; i < 33; i++) {
                        printf("%02x ", rvd_data[i]);
                    }
                    printf("\n");
                }

                // 断开当前连接，使用新获取的配置重新连接
                ESP_ERROR_CHECK(esp_wifi_disconnect());
                ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
                esp_wifi_connect();
                break;
            case SC_EVENT_SEND_ACK_DONE:
                // 智能配网确认发送完成，设置完成位
                //esp_smartconfig_stop(); // 停止智能配网
                xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
                break;

            default:
                break;
        }
    }
}

static time_t now;         // 存储当前时间戳
static struct tm timeinfo; // 存储分解的时间结构体

// 更新时间函数，由LVGL定时器每秒调用一次
void value_update_cb(lv_timer_t *timer)
{
    // 获取并更新系统时间
    time(&now);
    localtime_r(&now, &timeinfo); // 将时间戳转换为本地时间结构体

    update_current_date_to_screen(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday); // 更新日期显示

    update_current_time_to_screen(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); // 更新时间显示
    // // 格式化并更新时间标签文本 (时:分:秒)
    // lv_label_set_text_fmt(time_label, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
    // // 格式化并更新日期标签文本 (年-月-日)
    // lv_label_set_text_fmt(date_label, "%d年%02d月%02d日", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
}
// 获得网络时间的任务函数（在WiFi连接成功后创建）
static void get_time_task(void *pvParameters)
{
    // 等待WiFi连接成功事件位被置位
    xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);

    // 配置并初始化SNTP客户端，使用中国NTP池
    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("cn.pool.ntp.org");
    esp_netif_sntp_init(&config);
    // 等待时间同步完成，最多等待约2秒*重试次数
    int retry = 0;
    while (esp_netif_sntp_sync_wait(2000 / portTICK_PERIOD_MS) == ESP_ERR_TIMEOUT) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d)", retry++);
        if (retry >= 15)
            goto exit;
    }

    esp_netif_sntp_deinit(); // 时间同步完成后，反初始化SNTP
    // 设置时区为中国标准时间 (CST-8)
    setenv("TZ", "CST-8", 1);
    tzset(); // 使时区设置生效
    // 获取同步后的系统时间
    time(&now);
    localtime_r(&now, &timeinfo);
    ESP_LOGI(TAG, "Got system time: %d-%02d-%02d %02d:%02d:%02d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

    update_current_date_to_screen(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday); // 更新日期显示

    update_current_time_to_screen(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); // 更新时间显示

    // 设置事件位，表示已成功获取到SNTP时间（可能用于其他任务同步）
    xEventGroupSetBits(s_wifi_event_group, WIFI_GET_SNTP_BIT);

    // 创建LVGL定时器，每秒更新一次时间显示
    lv_timer_create(value_update_cb, 1000, NULL);
exit:
    vTaskDelete(NULL); // 任务完成，删除自身
}
struct tm *get_current_timeinfo(void) // 获取当前时间结构体
{
    return &timeinfo;
}

char *get_current_ip4(void) // 获取当前IP地址字符串
{
    return ip4_addr;
}
/*
 * @brief  wifi公共初始化函数(完成wifi基础配置)
*/
esp_netif_t *wifi_init(void)
{
    if (NULL == s_wifi_event_group)
        s_wifi_event_group = xEventGroupCreate();

    wifiset_deinit(); // 清除之前的初始化内容
    //!这个在main统一初始化
    //nvs_flash_init(); // 初始化nvs存储区
    // 创建默认的事件循环
    esp_event_loop_create_default();
    // 初始化网络接口
    esp_netif_init();
    // 注册WIFI事件回调函数
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_callback, NULL, &instance_any_id);  // 注册WIFI事件回调函数
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_callback, NULL, &instance_got_ip); // 注册IP获取事件回调函数
    // 创建sta模式的wifi接口
    sta_netif = esp_netif_create_default_wifi_sta();
    // 启动wifi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    // 设置wifi模式为STA
    esp_wifi_set_mode(WIFI_MODE_STA);
    // 启用wifi
    esp_wifi_start();
    esp_wifi_set_ps(WIFI_PS_NONE); //不省电模式
    is_scan = false;
    if (is_first_wifi_init == false) {
      //  xTaskCreatePinnedToCore(get_time_task, "get_time_task", 4 * 1024, NULL, 5, NULL, 0); // 创建获取网络时间的任务
      xTaskCreatePinnedToCoreWithCaps(get_time_task, "get_time_task", 4 * 1024, NULL, 5, NULL, 1,MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
      is_first_wifi_init = true;
    }
    return sta_netif;
}

// 扫描附近WiFi
esp_netif_t *wifi_scan(wifi_ap_record_t ap_info[], uint16_t *ap_number)
{
    sta_netif = wifi_init();
    is_scan = true;
    uint16_t ap_count = 0;
    memset(ap_info, 0, *ap_number * sizeof(wifi_ap_record_t));
    esp_wifi_scan_start(NULL, true); // 开始扫描
    ESP_LOGI(TAG, "Max AP number ap_info can hold = %u", *ap_number);
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));              // 获取扫描到的WiFi数量
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(ap_number, ap_info)); // 获取真实的获取到WiFi数量和信息
    ESP_LOGI(TAG, "Total APs scanned = %u, actual AP number ap_info holds = %u", ap_count, *ap_number);
    return sta_netif;
}

//
esp_netif_t *wifi_smartconfig(void)
{
    sta_netif = wifi_init();
    is_scan = true;
    ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &wifi_callback, NULL));
    EventBits_t uxBits;
    esp_smartconfig_stop();
    // 设置智能配网类型为ESPTOUCH
    esp_err_t err = esp_smartconfig_set_type(SC_TYPE_ESPTOUCH);
    ESP_LOGI(TAG, "esp_smartconfig_set_type ret: %d", err);
    // 使用默认配置启动智能配网
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));

    // while (1) {
    //     uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
    //     if (uxBits & CONNECTED_BIT) {
    //         ESP_LOGI(TAG, "WiFi Connected to ap");
    //     }
    //     if (uxBits & ESPTOUCH_DONE_BIT) {
    //         ESP_LOGI(TAG, "smartconfig over");
    //         esp_smartconfig_stop();
    //         vTaskDelete(NULL);
    //     }
    // }
    return sta_netif;
}

// 清除WiFi初始化内容，释放资源
void wifiset_deinit(void)
{
    if (NULL == sta_netif) {
        return;
    }
    /*清除连接成功事件*/
    xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    // 取消注册事件处理器
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &instance_got_ip));
    // 停止WiFi
    esp_err_t err = esp_wifi_stop();
    if (err == ESP_ERR_WIFI_NOT_INIT) {
        return; // 如果WiFi未初始化，则直接返回
    }
    ESP_ERROR_CHECK(err);
    // 反初始化WiFi驱动
    ESP_ERROR_CHECK(esp_wifi_deinit());
    // 清除默认的WiFi驱动和处理程序
    esp_err_t ret = esp_wifi_clear_default_wifi_driver_and_handlers(sta_netif);
    ESP_LOGI(TAG, "esp_wifi_clear_default_wifi_driver_and_handlers ret: %d", ret);
    // 销毁网络接口
    esp_netif_destroy(sta_netif);
    sta_netif = NULL; // 将指针置NULL
    // （可选）删除默认事件循环。注意：如果其他地方还在用，不能删除。
    // ESP_ERROR_CHECK(esp_event_loop_delete_default());
}